home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
turbovis
/
tvtoys04.zip
/
TIP.TXT
< prev
next >
Wrap
Text File
|
1993-12-07
|
10KB
|
368 lines
TIP.TXT
TVToys extra
PJB 1993, Internet mail to d91-pbr@nada.kth.se
Here are some general ideas that might and might not be
of interest to you.
-----
Do you have problems with SmartDrive not saving your programs before
they crash your computer? Try adding this code snippet before
MyApp.Init and SmartDrv will flush (write) its contents before your
program starts. You might want to enclose it with {$IFDEF Debug}
or something similar.
(* Flush SmartDrive disk cache, equivalent to "smartdrv /c" *)
asm
mov ax,4A10h
mov bx,1
int 2Fh
end;
-----
Do you want your program to retain the startup video mode even if
it is not recognized by Turbo Vision, like extended video modes?
Try this to keep the startup video mode active:
begin
if IsProbablyTextMode then
PreventModeSwitch;
MyApp.Init;
MyApp.Run;
MyApp.Done;
end.
The PreventModeSwitch makes Turbo Vision "forget" about resetting the
video mode to 2, 3 or 7. Use PreventModeSwitch before every call to
InitVideo (called by TApplication.Init and DosShell etc) to make Turbo
Vision accept the current video mode.
You can also put the if statement in your application's Init,
just make sure it executes before the inherited Init, like this:
constructor MyApp.Init;
begin
if IsProbablyTextMode then
PreventModeSwitch;
inherited Init;
end;
See also: RESTEST.PAS
-----
Are you short of memory and don't use the Tile/Cascade commands?
Make your MyApp.HandleEvent inherit TProgram's HandleEvent, not
TApplication's. That is, change your MyApp.HandleEvent's
inherited HandleEvent(Event);
into
TProgram.HandleEvent(Event);
TApplication also responds to cmDosShell, so you need to respond to
that yourself.
This makes your EXE file 2K (1940 bytes) smaller.
-----
Are you still short of memory? If you change HelpFile's TStreamRecs
so that neither has a Store you save 1.5K in TP6, but only 600 bytes
in BP7. Check out the Patch lines below.
Remember that you can't recompile TVHC without the Stores,
(well... you can, but TVHC won't work) so keep a copy of the original
HelpFile.
RHelpTopic: TStreamRec = (
ObjType: 10000;
VmtLink: Ofs(TypeOf(THelpTopic)^);
Load: @THelpTopic.Load;
Store: Nil {Patch}
);
RHelpIndex: TStreamRec = (
ObjType: 10001;
VmtLink: Ofs(TypeOf(THelpIndex)^);
Load: @THelpIndex.Load;
Store: Nil {Patch}
);
-----
Here are my favourite time saving BP IDE macros.
Please note that undoing the effects of any of these macros can
be very unreliable. Undo works better if you select group undo, I think.
(* This macro inserts "begin", a blank line, "end" and positions
the cursor on the blank line *)
MACRO PutBeginEnd
InsertText("begin\nend;");
CursorUp;
RightOfLine;
InsertText("\n ");
END;
(* This macro just inserts "{$}" and puts the cursor inside *)
MACRO PutDefine
InsertText("{$}");
CursorLeft;
END;
(* HERE IS A LIFE SAVER: it encloses the currently marked block with
"begin" and "end" keywords. You can do something similar for
{IFDEF} {ENDIF} and comments maybe *)
MACRO MakeBlock
MoveToBlockBeg;
CursorUp;
RightOfLine;
InsertText("\n");
InsertText("begin\nend;");
LeftOfLine;
MoveBlock;
MoveToBlockEnd;
END;
(* Here is a macro that produces button like shadows for use in help
files. To use it, type a header and execute the macro on the same
line. The current line is indented, a "▄" is appended and the next
line is completely overwritten with a shadow. If you change the
header, just delete the trailing "▄" and reexecute the macro.
MACRO MakeHelpShadow
CursorDown;
LeftOfLine;
InsertText(" ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀");
LeftOfLine;
CursorUp;
InsertText(" ");
LeftOfLine;
DeleteWord;
InsertText(" ");
RightOfLine;
InsertText(" ▄");
CursorDown;
DeleteToEol;
END;
(* I find that I use this command all the time, along with its move
companion. It copies a block but it places the cursor AFTER the
block, not before. Saves me A LOT of typing, now if I only could
figure out where to put the clipboard equivalent... *)
MACRO CopyMoveAfter
CopyBlock;
MoveToBlockEnd;
END;
-----
If you have a word wrapping text editor, you can install it as a tool in
BP (!) to do word wrap or other tasks that BP doesn't handle. The $LINE
macro is especially useful if only your editor supports it!
-----
Have you dreamed about ForEach style procedure calls? Don't like
assembler? Here is one way to do it.
Let's implement TCollection.ForEach as a demonstration.
Here is what you need:
(*******************************************************************
Below is a small system to call local procedures without
resorting to assembler.
*******************************************************************)
procedure DoNothing; far; assembler; asm end;
const
PushParameters : pointer = @DoNothing;
type
JumpToProc = procedure;
{$IFDEF Windows}
procedure PushPreviousBP; inline($8B/$46/$00/$24/$FE/$50);
(* MOV AX,[BP]
AND AL,0FEh
PUSH AX *)
{$ELSE}
procedure PushPreviousBP; inline($FF/$76/$00); (* PUSH WORD PTR [BP] *)
{$ENDIF}
(* You then need a procedural-type: *)
type
ActionProc = procedure (P:Pointer);
(*******************************************************************
*******************************************************************)
procedure TCollection.ForEach(Action:Pointer);
var
I : integer;
begin
for I:=0 to Count-1 do
begin
(* What we want to do: Action(Items^[I])
where Action is a pointer to a far procedure of the same
type as ActionProc.
The problem is that ActionProc(Action)(Items^[I])
doesn't set up the stack properly since we're calling
a LOCAL procedure *)
(* 1) First push the parameters: Simulate a call to an AddModeProc
while really calling a RETF, thus leaving the parameters on
the stack *)
ActionProc(PushParameters) (Items^[I]);
(* 2) Push the previous BP to set up the stack properly *)
PushPreviousBP;
(* 3) Call the procedure: JumpToProc is just a type cast to make
the compiler think that Action takes no parameters *)
JumpToProc(Action);
end;
end;
(*******************************************************************
*******************************************************************)
Assembler speaking, this is almost what happens:
asm
(* 1 *)
LES DI,Items^[I] (* Pseudo *)
PUSH ES
PUSH DI
{Meaningless DoNothing funtion call removed}
(* 2 *)
PUSH WORD PTR [BP]
(* 3 *)
CALL FAR Action
end;
-----
Here is what ScanEVGAModes in VIDEO.PAS used to look like
(*******************************************************************
procedure ScanVideoModes(First:Byte; AddMode:Pointer);
First: First video mode to try
AddMode: Procedure to call for each valid text video mode.
ScanVideoModes attempts to find out what video modes are available.
It tries to set every video mode possible, checking to see if
the BIOS put valid data for a text mode in the BIOS data segment.
ScanVideoModes starts at mode First and works its way up to mode
127. Every time a valid Text video mode is found, AddMode is called.
AddMode should be a FAR procedure with the same parameters as an
AddModeProc.
■ ScanVideoModes behaves like ForEach (TGroup, TCollection)
in Turbo